/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stream_buffer.h"
#include <stdio.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define BUFFER_LEN		80
#define TRIGGER_LEVEL	20
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
StreamBufferHandle_t streamBuffer;
/* USER CODE END Variables */
/* Definitions for Task_Main */
osThreadId_t Task_MainHandle;
const osThreadAttr_t Task_Main_attributes = { .name = "Task_Main", .stack_size =
		256 * 4, .priority = (osPriority_t) osPriorityNormal, };

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void AppTask_Main(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
 * @brief  FreeRTOS initialization
 * @param  None
 * @retval None
 */
void MX_FREERTOS_Init(void) {
	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* USER CODE BEGIN RTOS_MUTEX */
	/* add mutexes, ... */
	/* USER CODE END RTOS_MUTEX */

	/* USER CODE BEGIN RTOS_SEMAPHORES */
	/* add semaphores, ... */
	/* USER CODE END RTOS_SEMAPHORES */

	/* USER CODE BEGIN RTOS_TIMERS */
	/* start timers, add new ones, ... */
	/* USER CODE END RTOS_TIMERS */

	/* USER CODE BEGIN RTOS_QUEUES */
	/* add queues, ... */
	/* USER CODE END RTOS_QUEUES */

	/* Create the thread(s) */
	/* creation of Task_Main */
	Task_MainHandle = osThreadNew(AppTask_Main, NULL, &Task_Main_attributes);

	/* USER CODE BEGIN RTOS_THREADS */
	/* add threads, ... */
	streamBuffer = xStreamBufferCreate(BUFFER_LEN, TRIGGER_LEVEL);
	/* USER CODE END RTOS_THREADS */

	/* USER CODE BEGIN RTOS_EVENTS */
	/* add events, ... */
	/* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_AppTask_Main */
/**
 * @brief  Function implementing the Task_Main thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_AppTask_Main */
void AppTask_Main(void *argument) {
	/* USER CODE BEGIN AppTask_Main */
	uint32_t adcArray[10];
	uint16_t requiredBytes = 32;

	uint8_t temp_str[30];
	sprintf(temp_str, "Stream Buffer length = %d", BUFFER_LEN);
	lcd_show_str(10, 10 + 1 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Trigger Level = %d", TRIGGER_LEVEL);
	lcd_show_str(10, 10 + 2 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Required bytes = %d", requiredBytes);
	lcd_show_str(10, 10 + 3 * 30, 24, temp_str, RED);
	/* Infinite loop */
	for (;;) {
		uint16_t actualReadBytes = xStreamBufferReceive(streamBuffer, adcArray,
				requiredBytes, portMAX_DELAY);
		LED1_Toggle();

		uint8_t actualItems = actualReadBytes / 4;
		uint32_t sum = 0;
		for (uint8_t i = 0; i < actualItems; ++i) {
			sum += adcArray[i];
		}
		sum /= actualItems;

		sprintf(temp_str, "Actual read bytes = %d   ", actualReadBytes);
		lcd_show_str(10, 10 + 4 * 30, 24, temp_str, RED);

		sprintf(temp_str, "Average ADC Value = %d   ", sum);
		lcd_show_str(10, 10 + 5 * 30, 24, temp_str, RED);

		for (uint8_t i = 0; i < actualItems; ++i) {
			sprintf(temp_str, "[%d] = %d    ", i, adcArray[i]);
			lcd_show_str(10, 10 + (6 + i) * 30, 24, temp_str, RED);
		}


	}
	/* USER CODE END AppTask_Main */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
	if (hadc->Instance == ADC1) {
		uint32_t adc_value = HAL_ADC_GetValue(hadc);
		BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
		if (streamBuffer != NULL) {
			xStreamBufferSendFromISR(streamBuffer, &adc_value, 4,
					&pxHigherPriorityTaskWoken);
			portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
		}
	}
}
/* USER CODE END Application */

